//
//  HQL15_1ViewController.h
//  CoreAnimationDemo
//
//  Created by Qilin Hu on 2019/9/27.
//  Copyright © 2019 Tonintech. All rights reserved.
//

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

/// 用 CAShapeLayer 画一个圆角矩形
@interface HQL15_1ViewController : UIViewController

@end

NS_ASSUME_NONNULL_END

/*
 # 15.图层性能
 
 本章主要内容：图层渲染和组合相关的性能问题，着重图层树本身，以发掘最好的性能。
 
 ## 隐式绘制
 
 寄宿图可以通过 Core Graphics 直接绘制，也可以直接载入一个图片文件并赋值给 contents 属性，或事先绘制一个屏幕之外的 CGContext 上下文。
 在之前的两章中我们讨论了这些场景下的优化。但是除了常见的显式创建寄宿图，你也可以通过以下三种方式创建隐式的：
 1. 使用特性的图层属性。
 2. 特定的视图。
 3. 特定的图层子类。
 
 ## 文本
 
 CATextLayer 和 UILabel 都是直接将文本绘制在图层的寄宿图中。事实上这两种方式用了完全不同的渲染方式：在 iOS 6 及之前，UILabel 用 WebKit 的 HTML 渲染引擎来绘制文本，而 CATextLayer 用的是 Core Text. 后者渲染更迅速，所以在所有需要绘制大量文本的情形下都优先使用它吧。但是这两种方法都用了软件的方式绘制，因此他们实际上要比硬件加速合成方式要慢。

 不论如何，尽可能地避免改变那些包含文本的视图的 frame，因为这样做的话文本就需要重绘。
 例如，如果你想在图层的角落里显示一段静态的文本，但是这个图层经常改动，你就应该把文本放在一个子图层中。

 ## 光栅化
 
 > 开启此特性注意避免作用在内容不断变动的图层上
 
 在第四章『视觉效果』中我们提到了 CALayer 的 shouldRasterize 属性，它可以解决重叠透明图层的混合失灵问题。
 同样在第 12 章『速度的曲调』中，它也是作为绘制复杂图层树结构的优化方法。

 启用 shouldRasterize 属性会将图层绘制到一个屏幕之外的图像。然后这个图像将会被缓存起来并绘制到实际图层的 contents 和子图层。如果有很多的子图层或者有复杂的效果应用，这样做就会比重绘所有事务的所有帧划得来得多。但是光栅化原始图像需要时间，而且还会消耗额外的内存。
 
 当我们使用得当时，光栅化可以提供很大的性能优势（如你在第 12 章所见），但是一定要**避免作用在内容不断变动的图层上**，否则它缓存方面的好处就会消失，而且会让性能变的更糟。
 为了检测你是否正确地使用了光栅化方式，用 Instrument 查看一下 Color Hits Green 和 Misses Red 项目，是否已光栅化图像被频繁地刷新（这样就说明图层并不是光栅化的好选择，或则你无意间触发了不必要的改变导致了重绘行为）。
 
 ## 离屏渲染
 
当图层属性的混合体被指定为在未预合成之前不能直接在屏幕中绘制时，屏幕外渲染就被唤起了。
 屏幕外渲染并不意味着软件绘制，但是它意味着图层必须在被显示之前在一个屏幕外上下文中被渲染（不论 CPU 还是 GPU）。图层的以下属性将会触发屏幕外绘制：

 * 圆角（当和 maskToBounds 一起使用时）
 * 图层蒙板
 * 阴影

 屏幕外渲染和我们启用光栅化时相似，除了它并没有像光栅化图层那么消耗大，子图层并没有被影响到，而且结果也没有被缓存，所以不会有长期的内存占用。
 但是，如果太多图层在屏幕外渲染依然会影响到性能。
 
 有时候我们可以把那些需要屏幕外绘制的图层开启光栅化以作为一个优化方式，前提是这些图层并不会被频繁地重绘。
 对于那些需要动画而且要在屏幕外渲染的图层来说，你可以用 CAShapeLayer，contentsCenter 或者 shadowPath 来获得同样的表现而且较少地影响到性能。
 
 ## CAShapeLayer
 
 cornerRadius 和 maskToBounds 独立作用的时候都不会有太大的性能问题，但是当他俩结合在一起，就触发了屏幕外渲染。
 有时候你想显示圆角并沿着图层裁切子图层的时候，你可能会发现你并不需要沿着圆角裁切，这个情况下用 CAShapeLayer 就可以避免这个问题了。
 
 你想要的只是圆角且沿着矩形边界裁切，同时还不希望引起性能问题。
 其实你可以用现成的 UIBezierPath 的构造器 +bezierPathWithRoundedRect:cornerRadius:（见清单 15.1）.
 这样做并不会比直接用 cornerRadius 更快，但是它避免了性能问题。
 
 
 
 */
